'''
Created on 03-Apr-2010

@author: darsh
'''
from Util.util import debugmsg
from Client import Client
import Xlib
from Xlib import Xutil,X
from PyQt4 import QtCore
from Widgets.FrameWidget import FrameWidget



class ClientManager():
    """
    This class manages various things relating to the client that the WM handles.It includes features like scanning
    already existing clients and handlingvarious lient related events
    """
    def __init__(self):
        self.FRAMES=[]
        self.scan()      
    
    def scan(self):
        r = self.root.query_tree()
        for i in r.children:
            a = i.get_attributes()
            if a.map_state == X.IsViewable:
                self.addclient(i, self.currentdesktop)
                
    def HandleCreateNotify(self, ev):
        self.addclient(ev.window, self.currentdesktop)
        self.bringtofocus(ev.window)
    
    def HandleMapRequest(self, ev):
        debugmsg("Entering HandleMapRequest...........")

    def HandleUnMapNotify(self, ev):
        debugmsg("Entering HandleUnMapNotify...........")
        
    def HandleClientMessage(self, ev):
        #print ev.data[1][0]
        data = ev.data[1][0]
        #print data
        if ev.client_type == self.disp.intern_atom("_NET_CURRENT_DESKTOP"):
            self.HandleDesktopChangeMessage(data + 1)
        if ev.client_type == self.disp.intern_atom("_NET_WM_STATE"):
            self.HandleStateChange(ev)
       
    def HandleDesktopChangeMessage(self, desktop):
        self.switchtodesktop(desktop)

    def HandleStateChange(self, ev):
        """
        Handles state change messages sent by external applications to the window manager
        The first part of the message contains action which can be one of the following
        _NET_WM_STATE_REMOVE        0    /* remove/unset property */
        _NET_WM_STATE_ADD           1    /* add/set property */
        _NET_WM_STATE_TOGGLE        2    /* toggle property  */
        It is followed by the properties to alter,eg hidden state    
        Please consult EWMH spec for more details
        """
        print "Data"
        print ev.data
        action = ev.data[1][0]
        firstproperty = ev.data[1][1]
        print "Firstproperty"
        print firstproperty
        print "Action"
        print action
        if firstproperty == self.EWMH._HIDDEN:
            if action == 2:
                self.CLIENTS[ev.window].toggleiconify()
                    
    def HandleEnterNotify(self, ev):
        self.bringtofocus(ev.window)
    
    def HandleDestroyNotify(self, ev):
        debugmsg("Entering HandleDestroyNotify..........")
        self.removeclient(ev.window)
    
    def addclient(self, window, desktop):
        try:
            attrs = window.get_attributes()
            if attrs and attrs.override_redirect:
                return
            if self.isFrame(window):
                return
            if not window in self.CLIENTS:
                frame=FrameWidget()
                id=frame.winId()
                self.FRAMES.append(id)
                self.CLIENTS[window] = Client(window, self.root, desktop,frame)
                self.EWMH.setEWMHwindowdesktop(window, desktop - 1)
                self.EWMH.setEWMHwindowstate(window, [self.EWMH._ABOVE])
                self.EWMH.setEWMHWMState(window, [Xutil.NormalState])
                self.pushonfocusstack(window, desktop)
                #self.drawwindows()
            debugmsg("CLIENT AND FOCUS STATE AFTER WINDOW ADDITION:::")
            debugmsg(self.CLIENTS)
            self.EWMH.setEWMHclientlist([win.id for win in self.CLIENTS.keys()])
            #print "FOCUS STACK AFTER ADD IS:"+str(self.FOCUSSTACKS)
        except Xlib.error.BadWindow:
            pass
        
    def removeclient(self, window):
        if self.CLIENTS.has_key(window):
            desk = self.CLIENTS[window].desktop
            self.CLIENTS[window].framewidget.close()
            del self.CLIENTS[window]
            self.removefromfocusstack(window, desk)
            #self.drawwindows()
            #print "FOCUS STACKS AFTER REMOVAL ARE:"+str(self.FOCUSSTACKS)
        debugmsg("CLIENT STATE AFTER WINDOW REMOVAL:::")        
        debugmsg(self.CLIENTS)
        self.EWMH.setEWMHclientlist([win.id for win in self.CLIENTS.keys()])

    def getfocusedwindow(self, desktop):
        if desktop > 0 and desktop <= self.NUMBER_OF_DESKTOPS:
            if len(self.FOCUSSTACKS[desktop - 1]) > 0:
                return self.FOCUSSTACKS[desktop - 1][-1]
            
    def pushonfocusstack(self, window, desktop):
        self.FOCUSSTACKS[desktop - 1].append(window)
        self.EWMH.setEWMHstackedclientlist([win.id for win in self.FOCUSSTACKS[self.currentdesktop - 1]])

    def removefromfocusstack(self, window, desktop):
        if self.FOCUSSTACKS[desktop - 1].__contains__(window):
            self.FOCUSSTACKS[desktop - 1].remove(window)
            self.EWMH.setEWMHstackedclientlist([win.id for win in self.FOCUSSTACKS[self.currentdesktop - 1]])
            
    def bringtofocus(self, window):
        if self.CLIENTS.has_key(window):
            self.DisableMasks()
            desktop = self.CLIENTS[window].desktop
            self.removefromfocusstack(window, desktop)
            self.pushonfocusstack(window, desktop)
            self.drawwindows()
            #self.CLIENTS[window].focus()
            self.EnableMasks()
            
    def isFrame(self,window):
        return self.FRAMES.__contains__(window.id)
